package org.jtb.quickr;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.httpclient.methods.multipart.FilePart;
import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
import org.apache.commons.httpclient.methods.multipart.Part;
import org.apache.commons.httpclient.methods.multipart.StringPart;
import org.apache.log4j.Logger;

class MultipartPost extends Post {
    private static class PartComparator implements Comparator {
        public int compare(Object o1, Object o2) {
            Part p1 = (Part)o1;
            Part p2 = (Part)o2;
            
            return p1.getName().compareTo(p2.getName());
        }        
    }
    
    static Logger logger = Logger.getLogger(MultipartPost.class.getName());
    
    public MultipartPost(URL url, Map<String,Object> data) throws QuickrException {
        super(url, data);
    }    

    protected void addPostParameters(PostMethod postMethod) throws QuickrException {
        List<Part> parts = new ArrayList<Part>();
        
        // add simple string arg parts
        for (String key: getParameters().keySet()) {
            Object val = getParameters().get(key);
            
            Part part;
            if (val instanceof String) {
                part = new StringPart(key, (String)val);
            } else if (val instanceof File) {
                try {
                    part = new FilePart(key, (File)val);
                } catch (FileNotFoundException fnfe) {
                    throw new QuickrException("file not found for part key: " + key + ", val: " + val, fnfe);
                }
            } else {
                throw new QuickrException("unknown data type, key: " + val.getClass().getName() + " for key: " + key);
            }
            parts.add(part);
        }
        
        // this is not required, for debugging only
        Collections.sort(parts, new PartComparator());
                
        RequestEntity requestEntity = new MultipartRequestEntity(parts.toArray(new Part[0]), postMethod.getParams());
        
        if (logger.isDebugEnabled()) {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            try {
                requestEntity.writeRequest(baos);
                //logger.debug("upload request entity is:\n" + baos.toString());
            } catch (IOException ioe) {
                throw new QuickrException("could not debug request entity", ioe);
            }
        }
        
        postMethod.setRequestEntity(requestEntity);
    }        
}
